package com.deyuanyun.pic.settings.support.utils;

import com.deyuanyun.pic.settings.controller.dto.base.PipeScheduleVO;
import org.joda.time.DateTime;
import org.joda.time.LocalDateTime;
import org.joda.time.format.DateTimeFormat;

import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * cron表达式工具类
 *
 * @author axiao(xj08.dream@gmail.com)
 * @version 1.0
 *          Histroy: [修改人][时间][描述]
 * @date 2016-06-29
 */
public class CronUtils {

    /** 风险评价任务cron，每隔7天凌晨12点执行一次 */
    public final static String CRON_SEVEN_DAY = "0 5 0 */7 * ? ";
    /** 客户端调用接口失败后的内检测评价更新结果录入cron，每天凌晨0点十分执行一次 */
    public final static String CRON_CLIENT_FAIL_INSP_APPRAISE_DAY = "0 10 0 * * ? ";
    /** 客户端接口调用失败后的内检测录入cron，每天凌晨0点二十分执行一次 */
    public final static String CRON_CLIENT_FAIL_INSP_RESULT_DAY = "0 20 0 * * ? ";
    /** 客户端接口调用失败后的风险评价录入cron，每天凌晨0点半执行一次 */
    public final static String CRON_CLIENT_FAIL_RISK_INPUT_DAY = "0 30 0 * * ? ";

    /**
     * 管道管段任务周期实体类得到cron表达式
     *
     * @param pipeScheduleVO
     * @return 如果参数pipeScheduleVO为空，就返回null，否则就返回cron表达式，
     */
    public static String pipeCronStr(PipeScheduleVO pipeScheduleVO) {
        if (pipeScheduleVO != null) {
            int cycle = pipeScheduleVO.getCycle();
            int advance = pipeScheduleVO.getAdvance();
            //转换日期并设置的时间减去提前通知天数得到正确的提醒天数
            LocalDateTime dateTime = DateTimeFormat.forPattern("yyyy-MM").parseDateTime(pipeScheduleVO.getFirstTime()).toLocalDateTime().plusDays(-advance);
            if(dateTime == null) {
                return "";
            }
            int year = dateTime.getYear();
            //int month = dateTime.getMonthOfYear();
            int day = dateTime.getDayOfMonth();
            String dayStr = day + "";
            if(day > 28) //天数大于28的时候直接设置成每月的最后一天执行
                dayStr  = "L";

            //得到随机时间
            Calendar c = randomTime();
            int hour = c.get(Calendar.HOUR_OF_DAY);
            int minute = c.get(Calendar.MINUTE);
            int second = c.get(Calendar.SECOND);

            //初次执行时间
            LocalDateTime dateTime1 =  dateTime.withTime(hour, minute, second, 0);
            pipeScheduleVO.setStartDate(dateTime1.toDate());

            /*return MessageFormat.format("{6} {5} {4} {3} {1}/{2} ? {0,number,####}/1",
                    year, month, cycle, dayStr, hour, minute, second);*/

            return MessageFormat.format("{5} {4} {3} {2} */{1} ? {0,number,####}/1",
                    year, cycle, dayStr, hour, minute, second);

        }
        return null;
    }

    /**
     * 生成缺陷维修最迟维修提醒cron
     *
     * @param planRepairTime 维修时间
     * @return
     */
    public static Date getDefectNoticeCron(Date planRepairTime) {
        DateTime dateTime = new DateTime(planRepairTime);
        //得到随机时间
        Calendar randomCal = randomTime();
        DateTime d = dateTime.withTime(randomCal.get(Calendar.HOUR_OF_DAY), randomCal.get(Calendar.MINUTE),randomCal.get(Calendar.SECOND), 0);
        return d.toDate();
    }

    /**
     * 生成凌晨零点到凌晨3点的随机时间
     *
     * @return
     */
    private static Calendar randomTime() {
        try {
            String startTimeStr = "0:0:0";
            String endTimeStr = "3:0:0";
            SimpleDateFormat format = new SimpleDateFormat("H:m:s");
            Date start = format.parse(startTimeStr);
            Date end = format.parse(endTimeStr);

            long startL = start.getTime();
            long endL = end.getTime();
            if (startL > endL) {
                return null;
            }
            long f = random(startL, endL);
            Calendar c = Calendar.getInstance();
            c.setTimeInMillis(f);
            return c;
        } catch (Exception e) {

        }
        return null;
    }


    /**
     * 生成随机时间长整形
     *
     * @param start 开始时间长整形
     * @param end   结束时间长整形
     * @return
     */
    private static long random(long start, long end) {
        long f = start + (long) (Math.random() * (end - start));

        if (f == start || f == end) {
            return random(start, end);
        }
        return f;

    }

}
